#include "ThreadPool.h"
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <memory>
#include <functional>

using std::cout;
using std::endl;
using std::unique_ptr;
using std::bind;

class MyTask
{
public:
    void process(int x) 
    {
        //只需要根据具体的逻辑进行填充就可以了
        ::srand(::clock());
        int number = ::rand() % 100;
        cout << ">>BO_ThreadPool.MyTask number =  " << number << endl;
    }
};

//1、到底addTask执行了多少次，也就是添加了多少次任务？
//结果：任务确实是添加了20次，但是没有完全执行20次
//
//问题一：为何没有执行完所有的任务，程序就退出来了？
//原因：有可能当主线程添加完20次任务之后，立马执行stop函数，很快的将
//线程池退出的标志位_isExit设置为true，而子线程在doTask中执行的时候，
//while循环进不去，工作线程就被主线程回收了
//解决方案：只要任务队列不为空，即使主线程走到了stop，也让主线程阻塞等待
//任务执行完，所以在stop中添加了_taskQue.empty()的代码
//
//问题二：任务可以执行完毕，但是线程池无法退出来？
//原因：子线程在执行doTask函数获取任务与执行任务，而主线程执行stop函数
//如果子线程将所有的任务获取完毕之后，那么任务队列就为空了，那么此时
//主线程会在stop中继续向下执行，子线程也会向下执行process函数，那么
//如果主线程执行的比较快，就会将标志位_isExit设置为true，那么当子线程
//执行完process之后，在去走while循环的时候就进不到while循环，那么正好
//可以被主线程中的stop函数进行回收，所以这就是完美的结局；如果子线程
//获取完任务之后，执行的比较快，可能很快就执行完了process函数，然后
//又走到while循环了，而发现标志位_isExit还是为false，就又进入了while
//循环，那么子线程就会在_notEmpty条件变量上睡眠，那么主线程就不能回收
//子线程，程序就卡住了
//解决方案:在stop函数中，主线程在回收子线程的之前，有可能子线程在睡眠
//所以可以添加函数将所有等待在非空条件变量上的线程都唤醒，然后进行
//回收即可
void test()
{
    unique_ptr<MyTask> ptask(new MyTask());

    ThreadPool pool(4, 10);
    pool.start();

    int cnt = 20;
    while(cnt--)
    {
        //添加任务
        pool.addTask(bind(&MyTask::process, ptask.get(), 10));
        cout << "cnt = " << cnt << endl;
    }

    pool.stop();
}

int main(int argc, char *argv[])
{
    test();
    return 0;
}

